Problem
棋盘
Description
给定一个的棋盘,棋盘上每个位置要么为空要么为障碍。定义棋盘上两个位置能互相攻击当前仅当满足以下两个条件:
- 或
- 对于与之间的所有位置,均不是障碍。
现在有个询问,每个询问给定,要求从棋盘中选出个空位置来放棋子,问最少互相能攻击到的棋子对数是多少?
Input
第一行一个整数。
接下来输入一个的字符矩阵,一个位置若为.
,则表示这是一个空位置;若为#
,则为障碍。
第行输入一个整数代表询问个数。
接下来行,每行一个整数,代表要放的棋子个数。
Output
Sample Input
1 | 4 |
Sample Output
1 | 2 |
HINT
, ,
标签:费用流
Solution
“你见过拆点费用流吗?如果见过,那你见过拆边费用流吗?”
对于一块区域,若每个位置能互相攻击到,那么逐一放入棋子,第个放入的棋子会产生对新的攻击对关系。
注意到本题中这样的区域只可能是横着的或竖着的,这样我们可以预处理出若干个这样的横条和竖条,易知最多有个这样的区域。
按照以往的套路,我们将横条和竖条分开,这是因为对于一个格子,它同时在一个横条和一个竖条内。对于这样的每个横条,建一个点,并从源点连接到这个点。若这个横条中最多有个空位,那么流量最大为。然而每个单位流量的花费是不同的,于是建条边,第条边的费用为。对于每个竖条,建一个点,从这个点连到汇点,仍然建立条边,边权如法炮制。
之后对于每个点,找到其所在的横条和竖条,从横条的点连向竖条的点,流量费用。
跑费用流的时候,每次增广一定会新选一个格子,即流量增加。记录下每增加一个格子的最小冲突对数即最小花费,即可预处理出每个的答案。跑完费用流后再回答询问即可。
Code
1 |
|